Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • if (1) { a } else { b } tests/evaluates b...

    I have code of the form

    Code:
        if (1){
            d = 1
        } else {
            d = zxcv
        }
    where zxcv is undefined. Mata insists on looking in the else block, breaking my program. Is there some analogous code that I should be using here? (My real code is a little more complicated than this, with if () actually checking something, and some manipulations of zxcv being done before assignment to d.)

    Aside. This is quite infuriating and unexpected behavior. Mata does not need to look in the else block at all to evaluate my code. And the only workaround I can think of is coming up with dummy values for the zxcv object.

  • #2
    Here's my incredibly inelegant solution: nesting another if statement:

    Code:
     if (1){
            d = 1
        } else {
          if (1) {
            zxcv = 1
          }
            d = zxcv
        }
    To confirm that zxcv is not created, I use zxcv==J(0,0,.) (which is true no matter the third arg of J), as Mata has no exists() or confirm() function.

    Comment


    • #3
      I cannot replicate your problem, at least in non-interactive mode. Are you setting matatstrict on?

      .ÿ*!ÿshort-circuit.mata
      .ÿ
      .ÿversionÿ13.1

      .ÿ
      .ÿsetÿlinesizeÿ72

      .ÿ
      .ÿmata:
      -------------------------------------------------ÿmataÿ(typeÿendÿtoÿexit
      >ÿ)ÿ--------------------------------------------------------------------
      :ÿmataÿclear

      :ÿmataÿsetÿmatastrictÿoff

      :ÿ
      :ÿvoidÿfunctionÿtest1()ÿ{
      >ÿ
      >ÿÿÿÿÿÿÿÿÿifÿ(1)ÿ{
      >ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿdÿ=ÿ1
      >ÿÿÿÿÿÿÿÿÿ}
      >ÿÿÿÿÿÿÿÿÿelseÿ{
      >ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿdÿ=ÿxyz
      >ÿÿÿÿÿÿÿÿÿ}
      >ÿÿÿÿÿÿÿÿÿprintf("test1()ÿOK\n")
      >ÿ}
      note:ÿvariableÿxyzÿmayÿbeÿusedÿbeforeÿset
      note:ÿvariableÿdÿsetÿbutÿnotÿused

      :ÿ
      :ÿvoidÿfunctionÿtest2()ÿ{
      >ÿÿÿÿÿÿÿÿÿdÿ=ÿ(1ÿ?ÿ1ÿ:ÿxyz)
      >ÿÿÿÿÿÿÿÿÿprintf("test2()ÿOK\n")
      >ÿ}
      note:ÿvariableÿxyzÿmayÿbeÿusedÿbeforeÿset
      note:ÿvariableÿdÿsetÿbutÿnotÿused

      :ÿ
      :ÿvoidÿfunctionÿtest()ÿ{
      >ÿÿÿÿÿÿÿÿÿtest1()
      >ÿÿÿÿÿÿÿÿÿtest2()
      >ÿ}

      :ÿ
      :ÿtest()
      test1()ÿOK
      test2()ÿOK

      :ÿ
      :ÿend
      ------------------------------------------------------------------------

      .ÿ
      .ÿexit

      endÿofÿdo-file


      .


      I believe that in interactive mode, the compiler must be able to find the referents for all of the symbols (that are assigned, i.e., right-hand side) that it encounters as they are encountered. In non-interactive mode (above), I believe that the compiler is able to defer finding the referents to some degree.

      Comment


      • #4
        Thanks Joseph. I see the same result you do (without having turned matastrict on). I guess it is not an interactive-mode problem: if I write a do file containing just my code above -- not in a function -- and run the file in batch, the same problem occurs.

        Maybe I'm misunderstanding, but interactive refers to typing or pasting into the command window, right? By batch, I mean sending from my do-file editor. If you are referring to the in-vs-outside a function distinction, then I'm clear. It's good to know that the problem can be avoided in this way.

        Aside: That console output is in a really weird format. Where there should be a space you have the character "ÿ" in white. Try selecting it to copy-paste.

        Comment


        • #5
          Okay, now I'm running into a much more serious problem with this. I want to check if a file exists and then, if it does, to read it in with mata matuse and manipulate it.

          Code:
          capture confirm file "$indir/D0.mmat"
          local readit `=!_rc'
          
          mata
            if (`readit'){
              mata matuse "$indir/D0.mmat"
              // do other things with the new objects
          }
          end
          I guess I have to protect the operation inside a function as Joseph suggested, or put it all in a Stata if block with mata: prefixes (since Stata's if blocks are evaluated sensibly, but won't permit mata blocks inside them):

          Code:
          if `readit' {
              mata: mata matuse "$indir/D0.mmat"
              mata: // do other things with the new objects
          }
          I'm very interested in alternative suggestions.

          Comment


          • #6
            Hi Frank
            In the code just above you mix Stata and Mata code. readit is a Stata local.
            I think that in order to use it in Mata you must use -st_local-.
            But why not use -fileexists( )- directly from Mata?

            Try -help mata functions- then you will get an overview of Mata functions
            Kind regards

            nhb

            Comment


            • #7
              Ah, thank you, Niels. I didn't know about fileexists(). I suspect I'd still need an if (){... mata matuse ...} after using it, however, which leads back to the same problem.

              Using local or global macros in Mata can be done with the usual syntax. They simply substitute in text, as they do in Stata. st_local and st_global are needed to send Mata objects (formatted as strings) to macros. (I've just found this from experience, not the documentation, but it seems to work as I'd expect.)

              Comment


              • #8
                HI Frank
                Not necessarily. Looking into the code of -fileexists- I would do something like (I will always keep as much code as possible in Mata)

                Code:
                cls
                mata 
                    x = 1,2,3 \ 4,5,6
                    if ((fh = _fopen("mymatrix.myfile", "w")) >= 0) {
                        fputmatrix(fh, x)
                        fclose(fh)
                    }
                    if ((fh = _fopen("mymatrix.myfile", "r")) >= 0) {
                        test = fgetmatrix(fh)
                        fclose(fh)
                    }
                    test
                end
                Also note the documentation of -matuse- and -matsave- says
                These commands are for interactive use; they are not for use inside programs.
                Kind regards

                nhb

                Comment

                Working...
                X